﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace TreasureHunter
{
    public class HeapOfSquares
    {
        public List<Square> Heap = new List<Square>();
        private List<Square> fixedSquares = new List<Square>();
        public Square PlayableSquare;
        private Board board;

        public HeapOfSquares(Board board)
        {
            this.board = board;
            PlayableSquare = new Square(board, true, false, true, false);
        }

        public void FillBoardWithPieces()
        {
            MakePile();
            MakeDefaultCards();
            int placeCounter = 0;
            for (int x = 0; x < Board.BoardSize; x++)
            {
                for (int y = 0; y < Board.BoardSize; y++)
                {
                    if(ValidPosition(x, y))
                    {
                        this.Heap[placeCounter].Place(x, y);
                        placeCounter++;
                    }
                }
            }
        }

        /// <summary>
        /// Checks if a position on the board can be used to place a new piece on.
        /// </summary>
        /// <param name="x">X position/index</param>
        /// <param name="y">Y position/index</param>
        /// <returns></returns>
        private bool ValidPosition(int x, int y)
        {
            if (this.board.BoardGrid[x, y] != null)
            {
                if (!this.board.BoardGrid[x, y].IsFixed)
                {
                    return true;
                }
                else return false; //Position is used by a fixed item.
            }
            else return true;
        }

        /// <summary>
        /// Creates a pile of pieces that can be used in the game.
        /// </summary>
        private void MakePile()
        {
            List<Square> orderedPieces = new List<Square>();
            //create all playable pieces, 34 in total, and place 33 on the board. The remaining one is the leftover used for the game.

            //<------------------------------Replace by individual pieces.
            for (int i = 0; i < 11; i++)
            {
                orderedPieces.Add(new Square(this.board, false, true, false, true));
                orderedPieces.Add(new Square(this.board, true, false, true, false));
                orderedPieces.Add(new Square(this.board, true, true, true, false));
            }
            //<----------------------------------------------------------

            List<Square> randomizedPieces = orderedPieces;
            Shuffle(randomizedPieces);
            this.Heap = randomizedPieces;
        }

        /// <summary>
        /// Creates all of the default, fixed cards in the game and adds them to the list.
        /// </summary>
        private void MakeDefaultCards()
        {
            this.fixedSquares.Clear();
            //Create the cards
            Square topleft = new Square(true, this.board, false, true, true, false); //This should contain a green dot
            Square topright = new Square(true, this.board, false, false, true, true); //This should contain a red dot
            Square bottomright = new Square(true, this.board, true, false, false, true); //This should contain a yellow dot
            Square bottomleft = new Square(true, this.board, true, true, false, false); //This should contain a blue dot

            //North, two in the middle
            Square card31 = new Square(true, this.board, false, true, true, true);
            Square card51 = new Square(true, this.board, false, true, true, true);

            //East, two in the middle
            Square card73 = new Square(true, this.board, true, false, true, true);
            Square card75 = new Square(true, this.board, true, false, true, true);

            //South, two in the middle
            Square card37 = new Square(true, this.board, true, true, false, true);
            Square card57 = new Square(true, this.board, true, true, false, true);

            //West, two in the middle
            Square card13 = new Square(true, this.board, true, true, true, false);
            Square card15 = new Square(true, this.board, true, true, true, false);

            Square card33 = new Square(true, this.board, true, true, true, false);
            Square card53 = new Square(true, this.board, false, true, true, true);
            Square card55 = new Square(true, this.board, true, false, true, true);
            Square card35 = new Square(true, this.board, true, true, false, true);

            //Place cards on board
            topleft.Place(0, 0);
            topright.Place(Board.BoardSize - 1, 0);
            bottomright.Place(Board.BoardSize - 1, Board.BoardSize - 1);
            bottomleft.Place(0, Board.BoardSize - 1);

            card33.Place(2, 2);
            card53.Place(4, 2);
            card55.Place(4, 4);
            card35.Place(2, 4);

            card31.Place(2, 0);
            card51.Place(4, 0); //73 75   37 57   13 15

            card73.Place(6, 2);
            card75.Place(6, 4);

            card37.Place(2, 6);
            card57.Place(4, 6);

            card13.Place(0, 2);
            card15.Place(0, 4);

            //Add cards to the list of fixed cards
            this.fixedSquares.Add(topleft);
            this.fixedSquares.Add(topright);
            this.fixedSquares.Add(bottomright);
            this.fixedSquares.Add(bottomleft);

            this.fixedSquares.Add(card33);
            this.fixedSquares.Add(card53);
            this.fixedSquares.Add(card55);
            this.fixedSquares.Add(card35);

            this.fixedSquares.Add(card31);
            this.fixedSquares.Add(card51);

            this.fixedSquares.Add(card73);
            this.fixedSquares.Add(card75);

            this.fixedSquares.Add(card37);
            this.fixedSquares.Add(card57);

            this.fixedSquares.Add(card13);
            this.fixedSquares.Add(card15);
        }

        public void Shuffle<T>(IList<T> list)
        {
            RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
            int n = list.Count;
            while (n > 1)
            {
                byte[] box = new byte[1];
                do provider.GetBytes(box);
                while (!(box[0] < n * (Byte.MaxValue / n)));
                int k = (box[0] % n);
                n--;
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }
    }
}
